/*	--- 桥接(个人更愿意叫做: 纽带模式) --- 
(Bridge n. 纽带)


# 将【抽象部分】与【它的实现部分】分离，使它们都可以【独立地变化】。

-----------------------------------------------------


【桥接模式】的定义非常玄乎，直接理解不太容易，所以我们还是举例子。

假设【某个汽车厂商】生产【三种品牌的汽车】：
	Big、Tiny、Boss，

【每种品牌】又可以选择【燃油】、【纯电】和【混合动力】。

如果用【传统的继承】来表示【各个最终车型】，一共有【3个抽象类】加【9个最终子类】：

                   ┌───────┐
                   │  Car  │
                   └───────┘
                       ▲
    ┌──────────────────┼───────────────────┐
    │                  │                   │
┌───────┐          ┌───────┐          ┌───────┐
│BigCar │          │TinyCar│          │BossCar│
└───────┘          └───────┘          └───────┘
    ▲                  ▲                  ▲
    │                  │                  │
    │ ┌───────────────┐│ ┌───────────────┐│ ┌───────────────┐
    ├─│  BigFuelCar   │├─│  TinyFuelCar  │├─│  BossFuelCar  │
    │ └───────────────┘│ └───────────────┘│ └───────────────┘
    │ ┌───────────────┐│ ┌───────────────┐│ ┌───────────────┐
    ├─│BigElectricCar │├─│TinyElectricCar│├─│BossElectricCar│
    │ └───────────────┘│ └───────────────┘│ └───────────────┘
    │ ┌───────────────┐│ ┌───────────────┐│ ┌───────────────┐
    └─│ BigHybridCar  │└─│ TinyHybridCar │└─│ BossHybridCar │
      └───────────────┘  └───────────────┘  └───────────────┘



如果要【新增一个品牌】，或者【加一个新的引擎】（比如核动力），那么【子类的数量】增长更快。

所以，【桥接模式】就是为了避免【直接继承带来 の 子类爆炸】。

---------------------

我们来看看【桥接模式】如何解决上述问题。

在【桥接模式】中，首先把Car按【品牌】进行【子类化】，但是，【每个品牌】选择什么【发动机】，不再使用子类扩充，而是通过一个【抽象的“修正”类】，以【组合的形式】引入。我

们来看看具体的实现。

首先定义【抽象类Car】，它引用一个Engine： */
public abstract class Car {
	// 引用Engine
	protected Engine engine;

	public Car(Engine engine) {
		this.engine = engine;
	}

	public abstract void drive();
}


/*
Engine的定义如下： */
public interface Engine {
	void start();
}


/*
紧接着，在一个【“修正”的抽象类】 RefinedCar 中定义一些【额外操作】： */
public abstract class RefinedCar extends Car {
	public RefinedCar(Engine engine) {
		super(engine);
	}

	public void drive() {
		this.engine.start();
		System.out.println("Drive " + getBrand() + " car...");
	}

	public abstract String getBrand();
}


/*
这样一来，最终的【不同品牌】继承自【RefinedCar】，例如 BossCar： */
public class BossCar extends RefinedCar {
	public BossCar(Engine engine) {
		super(engine);
	}

	public String getBrand() {
		return "Boss";
	}
}


/*
而针对每一种引擎，继承自Engine，例如HybridEngine： */
public class HybridEngine implements Engine {
	public void start() {
		System.out.println("Start Hybrid Engine...");
	}
}


/*
【客户端】通过自己选择【一个品牌】，再配合【一种引擎】，得到最终的Car： */
RefinedCar car = new BossCar(new HybridEngine());
car.drive();


/*
使用桥接模式的好处在于，如果要增加一种引擎，只需要针对Engine派生一个新的子类; 如果要增加一个品牌，只需要针对RefinedCar派生一个子类.

任何【RefinedCar的子类】都可以和【任何一种Engine】自由组合，即【一辆汽车】的两个维度：【品牌】和【引擎】都可以独立地变化。


       ┌───────────┐
       │    Car    │
       └───────────┘
             ▲
             │
       ┌───────────┐       ┌─────────┐
       │RefinedCar │ ─ ─ ─>│ Engine  │
       └───────────┘       └─────────┘
             ▲                  ▲
    ┌────────┼────────┐         │ ┌──────────────┐
    │        │        │         ├─│  FuelEngine  │
┌───────┐┌───────┐┌───────┐     │ └──────────────┘
│BigCar ││TinyCar││BossCar│     │ ┌──────────────┐
└───────┘└───────┘└───────┘     ├─│ElectricEngine│
                                │ └──────────────┘
                                │ ┌──────────────┐
                                └─│ HybridEngine │
                                  └──────────────┘


【桥接模式】实现比较复杂，【实际应用】也非常少，但它提供的【设计思想】值得借鉴，即不要【过度使用继承】，而是【优先拆分】某些部件，使用【组合的方式】来【扩展功能】。



============================================================


#	练习

使用桥接模式扩展一种新的品牌和新的核动力引擎。 */
package.com.Disign_Mode.Bridge_Mode;

// Component_Right-Car
public abstract class Car {
	// 引用Engine
	protected Engine engine;

	public Car(Engine engine) { // new Car(new Engine())的奥秘在此
		this.engine = engine;
	} // 树中的new Car, 建立在new Engine()部件生成后的基础上

	public abstract void drive();
}

public abstract class RefinedCar extends Car {
	public RefinedCar(Engine engine) {
		super(engine);
	}

	public void drive() {
		this.engine.start();
		System.out.println("Drive " + getBrand() + " car...");
	}

	public abstract String getBrand();
}

// Component-Engine
public interface Engine {
	void start();
}

public class HybridEngine implements Engine {
	public void start() {
		System.out.println("Start Hybrid Engine...");
	}
}

// Instance
public class TeslaCar extneds RefinedCar {
	public TeslaCar(Engine engine) {
		super(engine);
	}

	@Override
	public String getBrand() {
		return "Tesla";
	}
}


RefinedCar car2 = new TeslaCar(new HybridEngine());
car2.drive();


/*=======================================================


#	----- 纽带模式 の 小结 ----- 


1. 【纽带模式】通过分离【一个抽象接口】和【它的实现部分】，使得【设计】可以按【2个维度】独立扩展。



-----------

个人核心理解:  
    纽带模式, 其意义在于将 【传统继承】的【单维度】叠高高模式 -> 【纽带模式, 多继承, 多合一】的【多维度】的顺序拼接
    (顺序, 很重要, 在拼接对象的时候)

【传统继承模式】的【单维度】, 如同整个【树】唯一一个【Root】

【纽带模式】的【多维度】, 实际上如同将【树的Root】拔掉, Root = 第一层Layer的所有合并(且有一个最终合并对象, 往往是第一层Layer的最右边, 从左到右 = 部件从小到大, 本例子中树第一层最右边即为Car)

--------------

【纽带模式】缺点:
	new Object()的时候相对麻烦


*/











